<?php
/**
 *      [迷你云] (C)2009-2012 南京恒为网络科技.
 *   软件仅供研究与学习使用，如需商用，请访问www.miniyun.cn获得授权
 * 
 */
?>
<?php

class MCopyController
    extends MApplicationComponent 
    implements MIController
{
    private $_from_path = null;
    private $_to_path   = null;
    private $_user_id   = null;
    private $_user_device_id = null;
    
    public function invoke($uri=null)
    {
                                parent::init();
        $params = $_REQUEST;
                if (isset($params) === false) {
            throw new MFileopsException(
                                        FXP::t('Bad Request'),
                                        MConst::HTTP_CODE_400);
        }
                        $user   = MUserManager::getInstance()->getCurrentUser();
        $device = MUserManager::getInstance()->getCurrentDevice();
        $this->_user_id             = $user->user_id;
        $user_nick                  = $user->user_name;
        $this->_user_device_id      = $device->device_id;
        
                                $locale = "bytes";
        if (isset($params["root"]) === false || 
                isset($params["from_path"]) === false || 
                isset($params["to_path"]) === false) {
            throw new MFileopsException(
                                        FXP::t('Bad Request'),
                                        MConst::HTTP_CODE_400);
        }
        if (isset($params["locale"])) {
            $locale = $params["locale"];
        }
        $root               = $params["root"];
        $this->_from_path   = $params["from_path"];
        $this->_to_path     = $params["to_path"];
        
                                $is_invalid = MUtils::checkNameInvalid(
                            MUtils::get_basename($this->_to_path));
        if ($is_invalid)
        {
            throw new MFileopsException(
                                        FXP::t('bad request'),
                                        MConst::HTTP_CODE_400);
        }
                                $this->_from_path = MUtils::convertStandardPath($this->_from_path);
        $this->_to_path   = MUtils::convertStandardPath($this->_to_path);
        if ($this->_from_path == "/" || 
            $this->_to_path == "/" || 
            $this->_from_path === false || 
            $this->_to_path === false)
        {
            throw new MFileopsException(
                        FXP::t('bad request'),
                        MConst::HTTP_CODE_400);
        }
        if ($this->_to_path[strlen($this->_to_path)-1] == "/")
        {
                        throw new MFileopsException(
                        FXP::t('goal file_name invaild'),
                        MConst::HTTP_CODE_403);
        }
        $this->_from_path = "/".$this->_user_id.$this->_from_path;
        $this->_to_path   = "/".$this->_user_id.$this->_to_path;
                                if (strpos($this->_to_path, $this->_from_path."/") === 0)
        {
            throw new MFileopsException(
                            FXP::t('can not copy into child directory'),
                            MConst::HTTP_CODE_403);
        }
        if ($this->_to_path == "/{$this->_user_id}" || $this->_to_path == "/{$this->_user_id}/")
        {
            throw new MFileopsException(
                            FXP::t('can not copy into null directory'),
                            MConst::HTTP_CODE_403);
        }
                                $query_to_path_db_file = MFiles::queryAllFilesByPath($this->_to_path);
        $isUpdate = false;
        if ($query_to_path_db_file)
        {
            if ($query_to_path_db_file[0]["is_deleted"] == false)
            {
                                throw new MFileopsException(
                            FXP::t('already a folder at the given destination'),
                            MConst::HTTP_CODE_403);
            }
            $isUpdate = true;
        }
                                $file_name   = MUtils::get_basename($this->_to_path);
        $query_from_path_db_file = MFiles::queryFilesByPath($this->_from_path);
        if ($query_from_path_db_file === false || empty($query_from_path_db_file))
        {
            throw new MFileopsException(
                FXP::t('The source file was not found at the specified path.'),
                MConst::HTTP_CODE_404);
        }
                                $parent_path        = dirname($this->_to_path);
        $create_folder      = new MCreateFolderController();
        $create_folder->_user_device_id = $this->_user_device_id;
        $create_folder->_user_id          = $this->_user_id;
        $parent_file_id     = $create_folder->handlerParentFolder($parent_path);
                                $file_detail = new MFiles();
        $file_detail->file_name         = $file_name;
        $file_detail->file_path         = $this->_to_path;
        $this->assembleFileDetail( 
                                    $file_name,
                                    $parent_file_id,
                                    $file_detail, 
                                    $query_from_path_db_file[0]);
                                if ($isUpdate)
        {
            $file_detail->event_uuid = MUtils::random_string(MConst::LEN_EVENT_UUID);
            $updates = array();
            $updates["file_update_time"]    = time();
            $updates["is_deleted"]          = intval(false);
            $updates["event_uuid"]           = $file_detail->event_uuid;
            $ret_value = MFiles::updateFileDetailByPath($this->_to_path, $updates);
        }
        else
        {
            $ret_value = MFiles::CreateFileDetail($file_detail, $this->_user_id);
        }
        if ($ret_value === false)
            {
                throw new MFileopsException(
                                            FXP::t('Internal Server Error'),
                                            MConst::HTTP_CODE_500);
            }
        $ret_value = MEvents::CreateEvents($this->_user_id,
                                           $this->_user_device_id, 
                                           $file_detail->event_action,
                                           $file_detail->file_path,
                                           $file_detail->file_path,
                                           $file_detail->event_uuid
                                           );
        if ($ret_value === false)
        {
            throw new MFileopsException(
                                        FXP::t('already a folder at the given destination'),
                                        MConst::HTTP_CODE_500);
        }
                                $create_array = array();
        if ($file_detail->file_type == MConst::OBJECT_TYPE_DIRECTORY)
        {
                                                $query_db_file = MFiles::queryFilesByPath($this->_to_path);
            if ($query_db_file === false || empty($query_db_file))
            {
                throw new MFileopsException(
                    FXP::t('The source file was not found at the specified path.'),
                    MConst::HTTP_CODE_404);
            }
            $file_detail->id = $query_db_file[0]["id"];
            $this->handlerChildrenFile($file_detail);
                                                $move_controller = new MMoveController();
            $create_array = $move_controller->handleChildrenVersions(
                                            $create_array, 
                                            $this->_user_id, 
                                            $user_nick, 
                                            $this->_from_path, 
                                            $this->_to_path, 
                                            $query_from_path_db_file[0]["id"]);
        }
        else
        {
            $file_meta = new MFileMetas();
            $file_meta->version_id = $query_from_path_db_file[0]["version_id"];
                                                $file_version = MFileMetas::queryFileMeta(
                                                        $this->_to_path, 
                                                        MConst::VERSION);
            $file_meta->is_add     = false;
            if ($file_version)
            {
                $meta_value = MUtils::getFileVersions(
                                                $file_meta->version_id, 
                                                MConst::CREATE_FILE, 
                                                $this->_user_id, 
                                                $user_nick,
                                                $file_version[0]["meta_value"]);
            }
            else 
            {
                $meta_value = MUtils::getFileVersions(
                                                $file_meta->version_id, 
                                                MConst::CREATE_FILE, 
                                                $this->_user_id, 
                                                $user_nick);
                $file_meta->is_add     = true;             }
            $file_meta->meta_value = $meta_value;
            $file_meta->file_path  = $this->_to_path;
            $create_array[$query_from_path_db_file[0]["file_path"]] = $file_meta; 
        }
                                $ret = MFileMetas::batchCreateFileMetas($create_array, MConst::VERSION);
        if ($ret === false)
        {
            throw new MFileopsException(
                                        FXP::t('Internal Server Error'),
                                        MConst::HTTP_CODE_500);
        }
                                foreach ($create_array as $key => $file_meta)
        {
            if ($file_meta->is_add === true)
            {
                                continue;
            }
            MFileMetas::updateFileMeta(
                                        $file_meta->file_path, 
                                        MConst::VERSION, 
                                        $file_meta->meta_value);
        }
        
        $response                   = array();
        $is_dir                     = true;
        if ($query_db_file[0]["file_type"] == MConst::OBJECT_TYPE_FILE)
        {
                        $mime_type                = "text/plain";
            $response["mime_type"]    = $mime_type;
            $is_dir                   = false;
            $response["thumb_exists"] = MUtils::isExistThumbnail($mime_type, (int)$query_db_file["file_size"]);
        }
        
        
        $size                       = $query_db_file[0]["file_size"];
        $response["size"]           = MUtils::getSizeByLocale($locale, $size);
        $response["bytes"]          = intval($size);
        
        
        $path                       = $this->_to_path;
        $index                      = strlen("/{$this->_user_id}");
        $path                       = substr($path, $index);
        $response["path"]           = $path;
        $response["root"]           = $root;
        $response["is_dir"]         = $is_dir;
        $response["rev"]            = strval($query_db_file[0]["version_id"]);
        $response["revision"]       = intval($query_db_file[0]["version_id"]);
        $response["modified"]       = MUtils::formatIntTime($query_db_file["file_update_time"]);
        
        echo json_encode($response);
    }
    
    public function handlerChildrenFile($file_detail)
    {
        $directories = array();           $files       = array();                                   $db_children_files = MFiles::queryChildrenFilesByParentFileID($file_detail->from_id);
        if ($db_children_files === false)
        {
            throw new MFileopsException(
                        FXP::t('Internal Server Error'),
                        MConst::HTTP_CODE_500);
        }
        if (empty($db_children_files))
        {
            $p = $file_detail->file_path;
            return ;         }
                                if (count($db_children_files) > MConst::MAX_FILES_COUNT)
        {
            throw new MFileopsException(
                        FXP::t('Too many file'),
                        MConst::HTTP_CODE_406);
        }
                                foreach ($db_children_files as $db_file)
        {
            $new_file_detail = new MFiles();
                                                if ($db_file["is_deleted"] == true)
            {
                continue;
            }
            $this->assembleFileDetail(
                                        $db_file['file_name'],
                                        $file_detail->id,
                                        $new_file_detail, 
                                        $db_file);
            array_push($files, $new_file_detail);
            if ($db_file["file_type"] == MConst::OBJECT_TYPE_DIRECTORY)
            {
                array_push($directories, $new_file_detail);
            }
        }
        if (empty($files))
        {
            return ;
        }
                                $ret = MFiles::batchCreateFileDetails(
                                        $this->_user_id, 
                                        $files);
        if ($ret === false || empty($ret))
        {
            throw new MFileopsException(
                FXP::t('The source file was not found at the specified path.'),
                MConst::HTTP_CODE_404);
        }
        $ret = MEvents::batchCreateEvents(
                                    $this->_user_id, 
                                    $this->_user_device_id, 
                                    $files);
        if ($ret === false || empty($ret))
        {
            throw new MFileopsException(
                FXP::t('The source file was not found at the specified path.'),
                MConst::HTTP_CODE_404);
        }
                                foreach ($directories as $file)
        {
                                                $query_db_directory = MFiles::queryFilesByPath(
                                                        $file->file_path);
            if ($query_db_directory === false || empty($query_db_directory))
            {
                throw new MFileopsException(
                    FXP::t('The source file was not found at the specified path.'),
                    MConst::HTTP_CODE_404);
            }
            $file->id        = $query_db_directory[0]["id"];
            $this->handlerChildrenFile($file);
        }
    }
    
    
    public function assembleFileDetail(
                                        $file_name,
                                        $parent_file_id,
                                        $file_detail, 
                                        $query_db_file)
    {
        $file_path                          = $query_db_file["file_path"];
        $file_detail->file_type             = $query_db_file["file_type"];
        $event_action = MConst::CREATE_DIRECTORY;
        $file_detail->context               = $file_path;
        if ($file_detail->file_type == MConst::OBJECT_TYPE_FILE)
        {
            $event_action = MConst::CREATE_FILE;
            $version_id  = $query_db_file["version_id"];
            $version     = MFileVersions::queryFileVersionByID($version_id);
            if (!empty($version)) {
                $file_detail->context               = $version[0]["file_signature"];
            }
        }
        $file_detail->from_id               = $query_db_file['id'];
        $file_detail->parent_file_id        = $parent_file_id;
        $file_detail->event_action          = $event_action;
        $file_detail->file_name             = $file_name;
        $file_detail->version_id            = $query_db_file["version_id"];
        $file_detail->file_size             = $query_db_file["file_size"];
        $file_detail->event_uuid            = MUtils::random_string(MConst::LEN_EVENT_UUID);
        $index      = strlen($this->_from_path);
        $file_path  = substr_replace($file_path, $this->_to_path, 0, $index);
        $file_detail->from_path             = $file_path;
        $file_detail->file_path             = $file_path;
        $file_detail->file_create_time      = time();
        $file_detail->file_update_time      = time();
        
    }
}
?>